package com.bifang.core.oplog.integration.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bifang.common.constant.CacheConst;
import com.bifang.common.constant.enums.common.AuTypeEnum;
import com.bifang.common.constant.enums.common.AuthStatusEnum;
import com.bifang.common.constant.enums.common.BoolEnum;
import com.bifang.common.constant.enums.common.FuncTypeEnum;
import com.bifang.common.constant.enums.common.OpTypeEnum;
import com.bifang.common.constant.enums.common.OperatingEnum;
import com.bifang.common.exception.AppException;
import com.bifang.common.util.CommonSecureUtil;
import com.bifang.common.util.FieldChangeUtil;
import com.bifang.common.util.OplogUtil;
import com.bifang.common.util.PagerUtil;
import com.bifang.common.helper.RedisHelper;
import com.bifang.common.util.SessionUtil;
import com.bifang.common.vo.DictVO;
import com.bifang.common.vo.FunctionVO;
import com.bifang.common.vo.ModifiedFieldVO;
import com.bifang.common.vo.OplogApiDetailVO;
import com.bifang.common.vo.OplogApiQueryVO;
import com.bifang.common.vo.OplogApiVO;
import com.bifang.common.vo.OplogChangeVO;
import com.bifang.common.vo.OplogDetailVO;
import com.bifang.common.vo.OplogInfo;
import com.bifang.common.vo.OplogVO;
import com.bifang.common.vo.RemarksInfoVO;
import com.bifang.common.vo.RemoveField;
import com.bifang.common.vo.RollbackVO;
import com.bifang.common.vo.RouterVO;
import com.bifang.common.vo.SelectVO;
import com.bifang.common.vo.SessionInfo;
import com.bifang.common.vo.TableChangeLogVO;
import com.bifang.common.vo.operation.OperationPeriodVO;
import com.bifang.common.vo.oplog.OplogUserRemarksVO;
import com.bifang.common.annotations.ApiService;
import com.bifang.common.annotations.OpApi;
import com.bifang.core.dao.model.DictSysUser;
import com.bifang.core.dao.model.Oplog;
import com.bifang.core.dao.model.OplogApi;
import com.bifang.core.dao.model.OplogApiHistory;
import com.bifang.core.dao.model.OplogFunction;
import com.bifang.core.dao.model.OplogHistory;
import com.bifang.core.dao.model.OplogRouter;
import com.bifang.core.dao.model.OplogTableChange;
import com.bifang.core.dao.model.OplogTableChangeh;
import com.bifang.core.dao.model.OplogUserRemarks;
import com.bifang.core.dao.service.DictSysUserService;
import com.bifang.core.dao.service.OplogApiHistoryService;
import com.bifang.core.dao.service.OplogApiService;
import com.bifang.core.dao.service.OplogFunctionService;
import com.bifang.core.dao.service.OplogHistoryService;
import com.bifang.core.dao.service.OplogRouterService;
import com.bifang.core.dao.service.OplogService;
import com.bifang.core.dao.service.OplogTableChangeService;
import com.bifang.core.dao.service.OplogTableChangehService;
import com.bifang.core.dao.service.OplogUserRemarksService;
import com.bifang.core.dict.integration.DictIntegration;
import com.bifang.core.oplog.integration.OperationPeriodIntegration;
import com.bifang.core.oplog.integration.OplogIntegration;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

@Service
@ApiService(funcCode = "OPLOG", title = "日志服务")
public class OplogIntegrationImpl implements OplogIntegration {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${system.config.user.encryption.flag}")
    private Boolean encryptionFlag;

    @Value("${system.config.oplog.history.flag}")
    private Boolean historyFlag;

    @Autowired private RedisHelper redisHelper;
    @Autowired private OplogService oplogService;
    @Autowired private OplogHistoryService oplogHistoryService;
    @Autowired private OplogApiService oplogApiService;
    @Autowired private OplogApiHistoryService oplogApiHistoryService;
    @Autowired private OplogTableChangeService oplogTableChangeService;
    @Autowired private OplogTableChangehService oplogTableChangehService;
    @Autowired private DictIntegration dictIntegration;
    @Autowired private OplogRouterService oplogRouterService;
    @Autowired private OperationPeriodIntegration operationPeriodIntegration;
    @Autowired private OplogFunctionService oplogFunctionService;
    @Autowired private OplogUserRemarksService oplogUserRemarksService;
    @Autowired private DictSysUserService dictSysUserService;

    @Override
    public Long saveOpLog(OplogVO oplogVO, Object obj, String auType, String dateType) {
        String accessToken = oplogVO.getAccessToken();
        if (StringUtils.isNotBlank(accessToken)) {
            String redisKey = CacheConst.ACCESS_TOKEN + ":" + accessToken;
            if (redisHelper.hasKey(redisKey)) {
                SessionInfo sessionInfo = (SessionInfo) redisHelper.get(redisKey);
                if (sessionInfo != null) {
                    if (StringUtils.isBlank(oplogVO.getOpUserId())) {
                        oplogVO.setOpUserId(sessionInfo.getUserId());
                    }
                    DictSysUser dictSysUser = dictSysUserService.getById(oplogVO.getOpUserId());
                    if (ObjectUtil.isNotNull(dictSysUser)) {
                        String fullName = dictSysUser.getFullName();
                        if (!StringUtils.isEmpty(fullName)) {
                            oplogVO.setOpName(fullName);
                        }
                    } else {
                        oplogVO.setOpName(sessionInfo.getFullName());
                    }
                    oplogVO.setClientId(sessionInfo.getClientId());
                    oplogVO.setUserType(sessionInfo.getUserType());
                    oplogVO.setEquipmentId(sessionInfo.getEquipmentId());
                    oplogVO.setLoginType(sessionInfo.getLoginType());
                    oplogVO.setEquipmentType(sessionInfo.getEquipmentType());
                    oplogVO.setOpenId(sessionInfo.getOpenId());
                    oplogVO.setSystemCode(sessionInfo.getSystemCode());
                    oplogVO.setSystemName(sessionInfo.getSystemName());
                    oplogVO.setVersion(sessionInfo.getVersion());
                }
            }
        }

        BeanWrapper beanWrapper = null;
        OplogInfo oplogInfo = new OplogInfo();
        Boolean logFlag = true;

        if (obj != null) {
            beanWrapper = new BeanWrapperImpl(obj);
            String dataField = dateType;

            if ("other".equals(dataField) || "batch".equals(dataField)) {
                dataField = "";
            }
            boolean flag = false;
            if (StringUtils.isNotBlank(dataField)) {
                if (beanWrapper.isWritableProperty(dataField)) {
                    if (beanWrapper.getPropertyValue(dataField) != null) {
                        flag = true;
                    }
                }
            }
            if (flag) {
                oplogVO.setDataId(beanWrapper.getPropertyValue(dataField).toString());
                oplogVO.setDataType(dateType);
            } else {
                if ("batch".equals(dataField)) {
                    oplogVO.setDataId("");
                    oplogVO.setDataType(dateType);
                }
            }
            // 启动节点需要判断是否存在未审核通过业务
            boolean checkOp = false;
            String notDoingOp = ""; // 需要校验正在审核中的业务
            if (StringUtils.isNotBlank(oplogVO.getDataId())) {
                if (AuTypeEnum.START.getType().equals(auType)) {
                    checkOp = true;
                } else if (AuTypeEnum.OTHER.getType().equals(auType)) {
                    if (oplogVO.getUnionOplogId() != null) {
                        // 针对批量业务等联合处理业务校验
                        Oplog unionOplog = oplogService.getById(oplogVO.getUnionOplogId());
                        if (unionOplog != null) {
                            if (AuTypeEnum.START.getType().equals(unionOplog.getAuType())) {
                                checkOp = true;
                            }
                        }
                    }
                }
            }
            String title = "";
            String summaryinfo = "";
            String routerId = oplogVO.getRouterId();
            if (StringUtils.isNotBlank(routerId)) {
                oplogVO.setRouterId(routerId);
                OplogRouter oplogRouter = getRouter(routerId);
                if (oplogRouter != null) {
                    // 路由设置为不记日志 则不保存操作日志
                    if (BoolEnum.FALSE.getType().equals(oplogRouter.getLogFlag())) {
                        logFlag = false;
                    }
                    oplogInfo.setLogFlag(oplogRouter.getLogFlag());
                    oplogInfo.setOperating(oplogRouter.getOperating());
                    oplogVO.setTitle(oplogRouter.getTitle());
                    oplogVO.setRollbackFlag(oplogRouter.getRollbackFlag());
                    oplogVO.setAuditFlag(oplogRouter.getAuditFlag());
                    summaryinfo = oplogRouter.getDigest();
                    notDoingOp = oplogRouter.getNotDoingOp();
                }
            }
            // 未办结校验
            if (checkOp) {
                DictVO dictVO =
                        dictIntegration.getDictByFieldAndKey(
                                "operationType", oplogVO.getOperationType());
                if (dictVO != null) {
                    // 数据字典中分类存的是功能编号
                    if (StringUtils.isNotBlank(dictVO.getClassify())) {
                        OplogFunction oplogFunction = this.getFunction(dictVO.getClassify());
                        if (oplogFunction != null) {
                            notDoingOp = oplogFunction.getNotDoingOp();
                        }
                    }
                }
                List<String> opList = new ArrayList<>();
                if (StringUtils.isNotBlank(notDoingOp)) {
                    opList =
                            Arrays.stream(notDoingOp.split(","))
                                    .map(s -> s)
                                    .collect(Collectors.toList());
                }
                opList.add(oplogVO.getOperationType());

                /*去除重复申报校验,业务自行控制
                QueryWrapper<Oplog> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(Oplog::getStatus,BoolEnum.TRUE.getType())
                        .eq(Oplog::getRbStatus,BoolEnum.FALSE.getType())
                        .in(Oplog::getOperationType,opList)
                        .eq(Oplog::getAuType,AuTypeEnum.START.getType())
                        .eq(Oplog::getDataId,oplogVO.getDataId())
                        .eq(Oplog::getAuthStatus,AuthStatusEnum.NODO.getType());
                long count = oplogService.count(queryWrapper);
                if (count>0){
                    throw new AppException("该数据（"+oplogVO.getDataId()+"）存在未办结数据，前先审批后再操作");
                }*/
            }
            if (logFlag && StringUtils.isBlank(oplogVO.getRemarks())) {
                // 设置摘要信息
                String remarks = "";
                if (StringUtils.isNotBlank(summaryinfo)) {
                    // 转义摘要
                    List<RemarksInfoVO> remarksInfoList =
                            JSONUtil.toList(summaryinfo, RemarksInfoVO.class);
                    if (!CollectionUtils.isEmpty(remarksInfoList)) {
                        int i = 1;
                        int size = remarksInfoList.size();
                        for (RemarksInfoVO remarksInfo : remarksInfoList) {
                            if (StringUtils.isNotBlank(remarksInfo.getTitle())) {
                                remarks = remarks + remarksInfo.getTitle() + ":";
                            }

                            String value = "";
                            if (StringUtils.isNotEmpty(remarksInfo.getField())) {
                                if (beanWrapper.isWritableProperty(remarksInfo.getField())) {
                                    value =
                                            beanWrapper
                                                    .getPropertyValue(remarksInfo.getField())
                                                    .toString();
                                }
                            }
                            // 下拉框需要转义
                            if (StringUtils.isNotBlank(value)) {
                                if ("select".equals(remarksInfo.getType())) {
                                    List<SelectVO> dictList =
                                            dictIntegration.getDictByDictField(
                                                    remarksInfo.getField());
                                    if (!CollectionUtils.isEmpty(dictList)) {
                                        for (SelectVO selectVO : dictList) {
                                            // 字段相同转义
                                            if (value.equals(selectVO.getDictKey())) {
                                                value = selectVO.getDictValue();
                                                break;
                                            }
                                        }
                                    }
                                }
                            }

                            if (StringUtils.isNotBlank(value)) {
                                remarks = remarks + value;
                            }
                            if (i < size) {
                                remarks = remarks + "；";
                            }
                            i++;
                        }
                    }
                }
                /*if (encryptionFlag){
                    remarks = CommonSecureUtil.aesEncrypt(remarks);
                }*/
                oplogVO.setRemarks(remarks);
            }
            // 组织id
            if (StringUtils.isBlank(oplogVO.getOrgId())) {
                if (beanWrapper.isWritableProperty("orgId")) {
                    if (null != beanWrapper.getPropertyValue("orgId")) {
                        oplogVO.setOrgId(beanWrapper.getPropertyValue("orgId").toString());
                    }
                }
            }
            if (StringUtils.isBlank(oplogVO.getOrgCode())) {
                if (beanWrapper.isWritableProperty("orgCode")) {
                    if (null != beanWrapper.getPropertyValue("orgCode")) {
                        oplogVO.setOrgCode(beanWrapper.getPropertyValue("orgCode").toString());
                    }
                }
            }
            if (beanWrapper.isWritableProperty("areaCode")) {
                if (null != beanWrapper.getPropertyValue("areaCode")) {
                    oplogVO.setAreaCode(beanWrapper.getPropertyValue("areaCode").toString());
                }
            }
            if (oplogVO.getPersonId() == null) {
                if (beanWrapper.isWritableProperty("personId")) {
                    if (null != beanWrapper.getPropertyValue("personId")) {
                        oplogVO.setPersonId(
                                Long.parseLong(
                                        beanWrapper.getPropertyValue("personId").toString()));
                    }
                }
            }
            if (beanWrapper.isWritableProperty("locationArea")) {
                if (null != beanWrapper.getPropertyValue("locationArea")) {
                    oplogVO.setLocationArea(
                            beanWrapper.getPropertyValue("locationArea").toString());
                }
            }
            oplogVO.setStatus(BoolEnum.TRUE.getType());
            oplogVO.setRbStatus(BoolEnum.FALSE.getType());
            Oplog oplog = Convert.convert(Oplog.class, oplogVO);

            oplog.setAuthStatus(AuthStatusEnum.NODO.getType());
            oplogService.save(oplog);
            if (historyFlag == null) {
                historyFlag = false;
            }
            if (historyFlag) {
                OplogHistory oplogHistory = Convert.convert(OplogHistory.class, oplog);
                oplogHistoryService.save(oplogHistory);
            }
            oplogVO.setOplogId(oplog.getOplogId());
            // 将oplogid赋值到类中
            if (beanWrapper != null) {
                if (beanWrapper.isWritableProperty("opOplogId")) {
                    beanWrapper.setPropertyValue("opOplogId", oplog.getOplogId());
                }
                if (beanWrapper.isWritableProperty("busNo")) {
                    beanWrapper.setPropertyValue("busNo", oplogVO.getBusNo());
                }
                if (beanWrapper.isWritableProperty("commentType")) {
                    if (beanWrapper.getPropertyValue("commentType") == null
                            || StringUtils.isBlank(
                                    beanWrapper.getPropertyValue("commentType").toString())) {
                        beanWrapper.setPropertyValue("commentType", oplogVO.getCommentType());
                    }
                }
            }
        }

        oplogInfo.setOplogId(oplogVO.getOplogId());
        oplogInfo.setAuType(oplogVO.getAuType());
        oplogInfo.setAuditFlag(oplogVO.getAuditFlag());
        oplogInfo.setOpRouterId(oplogVO.getRouterId());
        oplogInfo.setAccessToken(accessToken);
        oplogInfo.setReqIp(oplogVO.getReqIp());
        oplogInfo.setBusNo(oplogVO.getBusNo());
        oplogInfo.setOperationType(oplogVO.getOperationType());
        oplogInfo.setOperationName(oplogVO.getOperationName());
        oplogInfo.setCommentType(oplogVO.getCommentType());
        OplogUtil.insert(oplogInfo);
        return oplogVO.getOplogId();
    }

    @Override
    public void rollbackLog(Long oplogId, String rbUserId, String rbRemarks, boolean ignoreYm) {
        Oplog oplog = oplogService.getById(oplogId);
        if (oplog == null) {
            OplogHistory oplogHistory = oplogHistoryService.getById(oplogId);
            if (oplogHistory != null) {
                oplog = Convert.convert(Oplog.class, oplogHistory);
            } else {
                throw new AppException("需要回退的日志不存在");
            }
        }

        if (!BoolEnum.TRUE.getType().equals(oplog.getRollbackFlag())) {
            throw new AppException("该业务不能回退");
        }
        if (StringUtils.isNotBlank(oplog.getRouterId())) {
            RollbackVO rollbackVO = new RollbackVO();
            rollbackVO.setIgnoreYm(ignoreYm);
            checkCanRollback(oplog, rollbackVO);
        }
        if (StringUtils.isBlank(oplog.getRbStatus())
                || !BoolEnum.TRUE.getType().equals(oplog.getRbStatus())) {
            UpdateWrapper<Oplog> upOplog = new UpdateWrapper<>();
            upOplog.lambda()
                    .set(Oplog::getRbStatus, BoolEnum.TRUE.getType())
                    .set(Oplog::getRbRemarks, rbRemarks)
                    .set(Oplog::getRbUserId, rbUserId)
                    .set(Oplog::getRbTime, new Date())
                    .eq(Oplog::getOplogId, oplogId);
            oplogService.update(upOplog);
            if (historyFlag) {
                UpdateWrapper<OplogHistory> upOplogHi = new UpdateWrapper<>();
                upOplogHi
                        .lambda()
                        .set(OplogHistory::getRbStatus, BoolEnum.TRUE.getType())
                        .set(OplogHistory::getRbRemarks, rbRemarks)
                        .set(OplogHistory::getRbUserId, rbUserId)
                        .set(OplogHistory::getRbTime, new Date())
                        .eq(OplogHistory::getOplogId, oplogId);
                oplogHistoryService.update(upOplogHi);
            }
        }
    }

    @Override
    public void finshAuth(Long oplogId, String authUserId, String authStatus, String authRemarks) {
        Oplog oplog = oplogService.getById(oplogId);
        if (oplog == null) {
            return;
        }
        if (!BoolEnum.TRUE.getType().equals(oplog.getAuditFlag())) {
            return;
        }
        if (StringUtils.isBlank(oplog.getAuthStatus())
                || !AuthStatusEnum.NODO.getType().equals(oplog.getAuthStatus())) {
            UpdateWrapper<Oplog> upOplog = new UpdateWrapper<>();
            upOplog.lambda()
                    .set(Oplog::getAuthStatus, authStatus)
                    .set(Oplog::getAuthRemarks, authRemarks)
                    .set(Oplog::getAuthUserId, authUserId)
                    .set(Oplog::getAuthTime, new Date())
                    .eq(Oplog::getOplogId, oplogId);
            oplogService.update(upOplog);
            if (historyFlag) {
                UpdateWrapper<OplogHistory> upOplogHi = new UpdateWrapper<>();
                upOplogHi
                        .lambda()
                        .set(OplogHistory::getAuthStatus, authStatus)
                        .set(OplogHistory::getAuthRemarks, authRemarks)
                        .set(OplogHistory::getAuthUserId, authUserId)
                        .set(OplogHistory::getAuthTime, new Date())
                        .eq(OplogHistory::getOplogId, oplogId);
                oplogHistoryService.update(upOplogHi);
            }
        }
    }

    @Override
    @Async("oplogTaskExecutor")
    public void saveApiOpLog(OplogApiVO oplogApiVO) {
        int dateym =
                Integer.parseInt(DatePattern.PURE_DATE_FORMAT.format(new Date()).substring(0, 6));
        // 业务期 目前没有日历，直接用系统时间
        oplogApiVO.setYm(dateym);
        String accessToken = oplogApiVO.getAccessToken();
        if (StringUtils.isNotBlank(accessToken)) {
            String redisKey = CacheConst.ACCESS_TOKEN + ":" + accessToken;
            if (redisHelper.hasKey(redisKey)) {
                SessionInfo sessionInfo = (SessionInfo) redisHelper.get(redisKey);
                if (sessionInfo != null) {
                    oplogApiVO.setUserId(sessionInfo.getUserId());
                    oplogApiVO.setFullNme(sessionInfo.getFullName());
                    oplogApiVO.setClientId(sessionInfo.getClientId());
                    oplogApiVO.setUserType(sessionInfo.getUserType());
                    oplogApiVO.setEquipmentId(sessionInfo.getEquipmentId());
                    oplogApiVO.setLoginType(sessionInfo.getLoginType());
                    oplogApiVO.setEquipmentType(sessionInfo.getEquipmentType());
                    oplogApiVO.setOpenId(sessionInfo.getOpenId());
                    oplogApiVO.setSystemCode(sessionInfo.getSystemCode());
                    oplogApiVO.setSystemName(sessionInfo.getSystemName());
                    oplogApiVO.setVersion(sessionInfo.getVersion());
                }
            }
        }
        if (oplogApiVO.getEndTime() == null) {
            oplogApiVO.setEndTime(new Date());
        }
        BigDecimal countTimeMs =
                new BigDecimal(
                        oplogApiVO.getEndTime().getTime() - oplogApiVO.getBegTime().getTime());
        BigDecimal countTime =
                countTimeMs.divide(new BigDecimal(1000), 3, BigDecimal.ROUND_HALF_DOWN);
        oplogApiVO.setCountTime(countTime);
        if (StringUtils.isNotBlank(oplogApiVO.getMessage())
                && oplogApiVO.getMessage().length() > 400) {
            oplogApiVO.setMessage(oplogApiVO.getMessage().substring(0, 400));
        }
        OplogApi oplogApi = Convert.convert(OplogApi.class, oplogApiVO);
        if (StringUtils.isBlank(oplogApi.getReqLogId())) {
            oplogApi.setReqLogId(IdUtil.fastSimpleUUID());
        }
        oplogApiService.save(oplogApi);
        oplogApiVO.setReqLogId(oplogApi.getReqLogId());
    }

    @Override
    @Async("oplogTaskExecutor")
    public void updateApiOplog(OplogApiVO oplogApiVO) {
        if (oplogApiVO.getEndTime() == null) {
            oplogApiVO.setEndTime(new Date());
        }
        BigDecimal countTimeMs =
                new BigDecimal(
                        oplogApiVO.getEndTime().getTime() - oplogApiVO.getBegTime().getTime());
        BigDecimal countTime =
                countTimeMs.divide(new BigDecimal(1000), 3, BigDecimal.ROUND_HALF_DOWN);
        oplogApiVO.setCountTime(countTime);
        if (StringUtils.isNotBlank(oplogApiVO.getMessage())
                && oplogApiVO.getMessage().length() > 400) {
            oplogApiVO.setMessage(oplogApiVO.getMessage().substring(0, 400));
        }
        OplogApi oplogApi = Convert.convert(OplogApi.class, oplogApiVO);
        oplogApiService.saveOrUpdate(oplogApi);
    }

    @Override
    public Boolean saveChangeLog(TableChangeLogVO tableChangeLogVO) {
        Long oplogId = tableChangeLogVO.getOplogId();
        if (oplogId == null) {
            throw new AppException("日志id不能传空");
        }
        String opType = tableChangeLogVO.getOpType();
        if (StringUtils.isBlank(opType)) {
            throw new AppException("处理类型不能为空");
        }
        String opTable = tableChangeLogVO.getOpTable();
        if (StringUtils.isBlank(opTable)) {
            throw new AppException("处理的表不能为空");
        }
        String dataField = tableChangeLogVO.getDataField();
        if (StringUtils.isBlank(dataField)) {
            throw new AppException("唯一标识字段不能为空");
        }
        Class classType = tableChangeLogVO.getClassType();
        if (classType == null) {
            throw new AppException("表实体类不能为空");
        }
        Class maperClass = tableChangeLogVO.getMaperClass();
        if (maperClass == null) {
            throw new AppException("处理的表实体类不能为空");
        }
        Oplog oplog = oplogService.getById(oplogId);
        if (oplog == null) {
            throw new AppException("日志信息不存在(" + oplogId + ")");
        }
        List<OplogTableChange> insertList = new ArrayList<>();
        Object newObj = tableChangeLogVO.getNewObj();
        Object oldObj = tableChangeLogVO.getOldObj();
        if (OpTypeEnum.ADD.getType().equalsIgnoreCase(opType)) {
            if (newObj == null) {
                throw new AppException("新增数据不能为空");
            }
            if (StringUtils.isBlank(tableChangeLogVO.getUniqueValue())) {
                if (newObj instanceof List) {
                    List<Object> list = (List<Object>) tableChangeLogVO.getNewObj();
                    for (Object obj : list) {
                        insertList.add(
                                createTableChange(
                                        obj,
                                        null,
                                        maperClass,
                                        classType,
                                        dataField,
                                        oplog,
                                        opTable,
                                        opType,
                                        null));
                    }
                } else {
                    insertList.add(
                            createTableChange(
                                    newObj,
                                    null,
                                    maperClass,
                                    classType,
                                    dataField,
                                    oplog,
                                    opTable,
                                    opType,
                                    null));
                }
            } else {
                insertList.add(
                        createTableChange(
                                newObj,
                                null,
                                maperClass,
                                classType,
                                dataField,
                                oplog,
                                opTable,
                                opType,
                                tableChangeLogVO.getUniqueValue()));
            }
        }
        if (OpTypeEnum.EDIT.getType().equalsIgnoreCase(opType)) {
            if (newObj == null) {
                throw new AppException("修改后数据不能为空");
            }
            if (oldObj == null) {
                throw new AppException("修改前数据不能为空");
            }
            Map<String, Object> oldMap = getOldMap(oldObj, dataField);
            if (StringUtils.isBlank(tableChangeLogVO.getUniqueValue())) {
                if (newObj instanceof List) {
                    List<Object> list = (List<Object>) newObj;
                    for (Object obj : list) {
                        OplogTableChange oplogTableChange =
                                createTableChange(
                                        obj,
                                        oldMap,
                                        maperClass,
                                        classType,
                                        dataField,
                                        oplog,
                                        opTable,
                                        opType,
                                        null);
                        if (StringUtils.isNotBlank(oplogTableChange.getChangJson())) {
                            insertList.add(oplogTableChange);
                        }
                    }
                } else {
                    OplogTableChange oplogTableChange =
                            createTableChange(
                                    newObj,
                                    oldMap,
                                    maperClass,
                                    classType,
                                    dataField,
                                    oplog,
                                    opTable,
                                    opType,
                                    null);
                    if (StringUtils.isNotBlank(oplogTableChange.getChangJson())) {
                        insertList.add(oplogTableChange);
                    }
                }
            } else {
                OplogTableChange oplogTableChange =
                        createTableChange(
                                newObj,
                                oldMap,
                                maperClass,
                                classType,
                                dataField,
                                oplog,
                                opTable,
                                opType,
                                tableChangeLogVO.getUniqueValue());
                if (StringUtils.isNotBlank(oplogTableChange.getChangJson())) {
                    insertList.add(oplogTableChange);
                }
            }
        }
        if (OpTypeEnum.DEL.getType().equalsIgnoreCase(opType)
                || OpTypeEnum.DELETE.getType().equalsIgnoreCase(opType)) {
            if (oldObj == null) {
                throw new AppException("删除数据不能为空");
            }
            if (StringUtils.isBlank(tableChangeLogVO.getUniqueValue())) {
                if (oldObj instanceof List) {
                    List<Object> list = (List<Object>) oldObj;
                    for (Object obj : list) {
                        insertList.add(
                                createTableChange(
                                        obj,
                                        null,
                                        maperClass,
                                        classType,
                                        dataField,
                                        oplog,
                                        opTable,
                                        opType,
                                        null));
                    }
                } else {
                    insertList.add(
                            createTableChange(
                                    oldObj,
                                    null,
                                    maperClass,
                                    classType,
                                    dataField,
                                    oplog,
                                    opTable,
                                    opType,
                                    null));
                }
            } else {
                insertList.add(
                        createTableChange(
                                oldObj,
                                null,
                                maperClass,
                                classType,
                                dataField,
                                oplog,
                                opTable,
                                opType,
                                tableChangeLogVO.getUniqueValue()));
            }
        }
        if (!CollectionUtils.isEmpty(insertList)) {
            /***
             * oplogTableChangeService.saveBatch(insertList);
             * if (historyFlag){
             * List<OplogTableChangeh>  insertHList=Convert.toList(OplogTableChangeh.class,insertList);
             * oplogTableChangehService.saveBatch(insertHList);
             * }***/
            return true;
        }
        return false;
    }

    @Override
    public List<OplogChangeVO> toList(Class elementType, Long oplogId, String opTable) {
        QueryWrapper<OplogTableChange> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(OplogTableChange::getOplogId, oplogId)
                .eq(OplogTableChange::getOpTable, opTable)
                .eq(OplogTableChange::getStatus, BoolEnum.TRUE.getType());
        List<OplogTableChange> list = oplogTableChangeService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<OplogChangeVO> opLogChangeVOS = new ArrayList<>();
        for (OplogTableChange oplogTableChange : list) {
            OplogChangeVO opLogChangeVO = Convert.convert(OplogChangeVO.class, oplogTableChange);
            if (StringUtils.isNotBlank(oplogTableChange.getChangJson())) {
                opLogChangeVO.setChangeList(
                        JSONUtil.toList(oplogTableChange.getChangJson(), ModifiedFieldVO.class));
            }
            if (StringUtils.isNotBlank(oplogTableChange.getTableJson())) {
                if (OpTypeEnum.DEL.getType().equals(oplogTableChange.getOpType())
                        || OpTypeEnum.DELETE.getType().equals(oplogTableChange.getOpType())) {
                    opLogChangeVO.setBeforeInfo(
                            JSONUtil.toBean(oplogTableChange.getTableJson(), elementType));
                } else if (OpTypeEnum.ADD.getType().equals(oplogTableChange.getOpType())) {
                    opLogChangeVO.setAfterInfo(
                            JSONUtil.toBean(oplogTableChange.getTableJson(), elementType));
                } else if (OpTypeEnum.EDIT.getType().equals(oplogTableChange.getOpType())) {
                    Object afterInfo =
                            JSONUtil.toBean(oplogTableChange.getTableJson(), elementType);
                    opLogChangeVO.setAfterInfo(afterInfo);
                    // 生成变动前数据
                    Object beforeInfo = Convert.convert(elementType, afterInfo);
                    getBeforInfo(beforeInfo, opLogChangeVO.getChangeList());
                }
            }

            opLogChangeVOS.add(opLogChangeVO);
        }
        return opLogChangeVOS;
    }

    @Override
    public List<OplogChangeVO> getTableChange(Long oplogId) {
        return null;
    }

    @Override
    @OpApi(funcCode = "OPLOG0001", title = "api接口日志列表查询", funcType = FuncTypeEnum.query)
    public PageInfo<OplogApiVO> getSysApiLogList(OplogApiQueryVO vo) {
        if (vo.getHistory() == null) {
            // 默认查询在线表
            vo.setHistory(false);
        }
        if (vo.getPageNum() != null && vo.getPageSize() != null) {
            PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        }
        if (vo.getHistory()) {
            Map<String, Object> map = BeanUtil.beanToMap(vo, false, true);
            if (CollectionUtils.isEmpty(map)) {
                throw new AppException("查询历史数据，查询条件不能为空");
            }
            List<OplogApiHistory> reqList = oplogApiHistoryService.selectByObject(vo);
            if (CollectionUtils.isEmpty(reqList)) {
                return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
            }
            PageInfo<OplogApiHistory> reqPageInfo = new PageInfo<>(reqList);
            List<OplogApiVO> list = new ArrayList<>();
            for (OplogApiHistory oplog : reqPageInfo.getList()) {
                OplogApiVO oplogApiVO = Convert.convert(OplogApiVO.class, oplog);
                if (encryptionFlag) {
                    oplogApiVO.setResBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getResBody()));
                    oplogApiVO.setReqBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getReqBody()));
                }
                list.add(oplogApiVO);
            }

            return PagerUtil.parsePagerVo(list, reqPageInfo);
        } else {
            List<OplogApi> reqList = oplogApiService.selectByObject(vo);
            if (CollectionUtils.isEmpty(reqList)) {
                return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
            }
            PageInfo<OplogApi> reqPageInfo = new PageInfo<>(reqList);
            List<OplogApiVO> list = new ArrayList<>();
            for (OplogApi oplog : reqPageInfo.getList()) {
                OplogApiVO oplogApiVO = Convert.convert(OplogApiVO.class, oplog);
                if (encryptionFlag) {
                    oplogApiVO.setResBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getResBody()));
                    oplogApiVO.setReqBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getReqBody()));
                }
                list.add(oplogApiVO);
            }
            return PagerUtil.parsePagerVo(list, reqPageInfo);
        }
    }

    @Override
    @OpApi(funcCode = "OPLOG0002", title = "api日志详情查询", funcType = FuncTypeEnum.query)
    public OplogApiVO getSysApiLogDetail(OplogApiDetailVO vo) {
        OplogApiVO oplogApiVO = getOplogApiDetail(vo.getReqLogId());
        if (oplogApiVO == null) {
            throw new AppException("请求日志详情不存在");
        }
        return oplogApiVO;
    }

    @Override
    public OplogApiVO getOplogApiDetail(String reqLogId) {
        if (StringUtils.isBlank(reqLogId)) {
            throw new AppException("请求日志id不能为空");
        }
        OplogApiVO oplogApiVO = null;
        OplogApi oplogApi = oplogApiService.getById(reqLogId);
        if (oplogApi == null) {
            OplogApiHistory oplogApiHistory = oplogApiHistoryService.getById(reqLogId);
            if (oplogApiHistory != null) {
                oplogApiVO = Convert.convert(OplogApiVO.class, oplogApiHistory);
            }

        } else {
            oplogApiVO = Convert.convert(OplogApiVO.class, oplogApi);
        }
        if (encryptionFlag) {
            oplogApiVO.setResBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getResBody()));
            oplogApiVO.setReqBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getReqBody()));
        }
        return oplogApiVO;
    }

    @Override
    public List<OplogApiVO> getOplogApiByOplogId(Long oplogId) {
        if (oplogId == null) {
            throw new AppException("操作日志id不能为空");
        }
        QueryWrapper<OplogApi> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(OplogApi::getOplogId, oplogId).orderByAsc(OplogApi::getBegTime);
        List<OplogApi> list = oplogApiService.list(queryWrapper);
        List<OplogApiVO> volist = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (OplogApi oplog : list) {
                OplogApiVO oplogApiVO = Convert.convert(OplogApiVO.class, oplog);
                if (encryptionFlag) {
                    oplogApiVO.setResBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getResBody()));
                    oplogApiVO.setReqBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getReqBody()));
                }
                volist.add(oplogApiVO);
            }
            return volist;
        }
        QueryWrapper<OplogApiHistory> historyQueryWrapper = new QueryWrapper<>();
        historyQueryWrapper
                .lambda()
                .eq(OplogApiHistory::getOplogId, oplogId)
                .orderByAsc(OplogApiHistory::getBegTime);
        List<OplogApiHistory> historyList = oplogApiHistoryService.list(historyQueryWrapper);
        if (!CollectionUtils.isEmpty(historyList)) {
            for (OplogApiHistory oplog : historyList) {
                OplogApiVO oplogApiVO = Convert.convert(OplogApiVO.class, oplog);
                if (encryptionFlag) {
                    oplogApiVO.setResBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getResBody()));
                    oplogApiVO.setReqBody(CommonSecureUtil.aesDecrypt(oplogApiVO.getReqBody()));
                }
                volist.add(oplogApiVO);
            }
            return volist;
        }
        return new ArrayList<>();
    }

    private synchronized OplogTableChange createTableChange(
            Object obj,
            Map<String, Object> oldMap,
            Class maperClass,
            Class classType,
            String dataField,
            Oplog oplog,
            String opTable,
            String opType,
            String uniqueValue) {
        if (StringUtils.isBlank(uniqueValue)) {
            uniqueValue = getUniqueValue(obj, dataField);
        }
        OplogTableChange oplogTableChange = new OplogTableChange();
        Integer orderNo = 1;
        QueryWrapper<OplogTableChange> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(OplogTableChange::getLastFlag, BoolEnum.TRUE.getType())
                .eq(OplogTableChange::getDataType, dataField)
                .eq(OplogTableChange::getUniqueValue, uniqueValue)
                .eq(OplogTableChange::getOpTable, opTable);
        OplogTableChange oldChange = oplogTableChangeService.getOne(queryWrapper);
        if (oldChange != null) {
            oplogTableChange.setSupChangeId(oldChange.getChangeId());
            if (oldChange.getOrderNo() != null) {
                orderNo = oldChange.getOrderNo() + 1;
            }
            UpdateWrapper<OplogTableChange> upLast = new UpdateWrapper<>();
            upLast.lambda()
                    .set(OplogTableChange::getLastFlag, BoolEnum.FALSE.getType())
                    .eq(OplogTableChange::getChangeId, oldChange.getChangeId());
            oplogTableChangeService.update(upLast);
            if (historyFlag) {
                UpdateWrapper<OplogTableChangeh> upHLast = new UpdateWrapper<>();
                upHLast.lambda()
                        .set(OplogTableChangeh::getLastFlag, BoolEnum.FALSE.getType())
                        .eq(OplogTableChangeh::getChangeId, oldChange.getChangeId());
                oplogTableChangehService.update(upHLast);
            }
        }
        oplogTableChange.setOrderNo(orderNo);
        oplogTableChange.setTableJson(JSONUtil.toJsonStr(obj));
        oplogTableChange.setDataType(dataField);
        oplogTableChange.setBeanClassPath(classType.getName());
        String className = maperClass.getSimpleName();
        oplogTableChange.setMapperClassName(
                className.substring(0, 1).toLowerCase() + className.substring(1));
        oplogTableChange.setDateYm(oplog.getDateYm());
        oplogTableChange.setOplogId(oplog.getOplogId());
        oplogTableChange.setCreateTime(new Date());
        oplogTableChange.setStatus(BoolEnum.TRUE.getType());
        oplogTableChange.setOpTable(opTable);
        oplogTableChange.setLastFlag(BoolEnum.TRUE.getType());
        oplogTableChange.setOpType(opType);
        oplogTableChange.setUniqueValue(uniqueValue);
        if (OpTypeEnum.EDIT.getType().equalsIgnoreCase(opType)) {
            if (!CollectionUtils.isEmpty(oldMap)) {
                Object oldObj = oldMap.get(uniqueValue);
                if (oldObj == null) {
                    throw new AppException("变动前数据不能为空");
                }
                List<ModifiedFieldVO> changList =
                        FieldChangeUtil.getModifyContentRemove(
                                oldObj, obj, RemoveField.getBaseRemove());
                if (!CollectionUtils.isEmpty(changList)) {
                    oplogTableChange.setChangJson(JSONUtil.toJsonStr(changList));
                }
            } else {
                throw new AppException("变动前数据不能为空");
            }
        }
        oplogTableChangeService.save(oplogTableChange);
        if (historyFlag) {
            OplogTableChangeh insertH = Convert.convert(OplogTableChangeh.class, oplogTableChange);
            oplogTableChangehService.save(insertH);
        }
        return oplogTableChange;
    }

    private String getUniqueValue(Object obj, String dataField) {
        if (obj == null) {
            throw new AppException("处理数据不能为空");
        }
        BeanWrapper beanWrapper = new BeanWrapperImpl(obj);
        String uniqueValue = "";
        if (StringUtils.isNotBlank(dataField)) {
            if (beanWrapper.isWritableProperty(dataField)) {
                if (beanWrapper.getPropertyValue(dataField) != null) {
                    uniqueValue = beanWrapper.getPropertyValue(dataField).toString();
                }
            }
        } else {
            throw new AppException("唯一标识所属字段名不能为空");
        }
        if (StringUtils.isBlank(uniqueValue)) {
            throw new AppException("未获取到唯一字段值");
        }
        return uniqueValue;
    }

    private Map<String, Object> getOldMap(Object oldObj, String dataField) {
        Map<String, Object> oldMap = new HashMap<>();
        if (oldObj instanceof List) {
            List<Object> list = (List<Object>) oldObj;
            for (Object old : list) {
                String oldValue = getUniqueValue(old, dataField);
                oldMap.put(oldValue, old);
            }
        } else {
            String oldValue = getUniqueValue(oldObj, dataField);
            oldMap.put(oldValue, oldObj);
        }
        return oldMap;
    }

    @Override
    public void getBeforInfo(Object argument, List<ModifiedFieldVO> changList) {
        if (!CollectionUtils.isEmpty(changList)) {
            BeanWrapper beanWrapper = new BeanWrapperImpl(argument);
            for (ModifiedFieldVO modifiedFieldVO : changList) {
                if (beanWrapper.isWritableProperty(modifiedFieldVO.getField())) {
                    Class cls = beanWrapper.getPropertyType(modifiedFieldVO.getField());
                    String type = cls.getSimpleName();
                    // 时间戳格式化时间
                    if (type.equals("Date") && isNumeric(modifiedFieldVO.getBeforeValue())) {
                        Date beforeDate =
                                new Date(
                                        Long.parseLong(
                                                String.valueOf(modifiedFieldVO.getBeforeValue())));
                        modifiedFieldVO.setBeforeValue(beforeDate.toString());
                        beanWrapper.setPropertyValue(modifiedFieldVO.getField(), beforeDate);
                    } else {
                        beanWrapper.setPropertyValue(
                                modifiedFieldVO.getField(), modifiedFieldVO.getBeforeValue());
                    }
                }
            }
        }
    }

    @Override
    public void getAfterInfo(Object argument, List<ModifiedFieldVO> changList) {
        if (!CollectionUtils.isEmpty(changList)) {
            BeanWrapper beanWrapper = new BeanWrapperImpl(argument);
            for (ModifiedFieldVO modifiedFieldVO : changList) {
                if (beanWrapper.isWritableProperty(modifiedFieldVO.getField())) {
                    Class cls = beanWrapper.getPropertyType(modifiedFieldVO.getField());
                    String type = cls.getSimpleName();
                    // 时间戳格式化时间
                    if (type.equals("Date") && isNumeric(modifiedFieldVO.getAfterValue())) {
                        Date afterDate =
                                new Date(
                                        Long.parseLong(
                                                String.valueOf(modifiedFieldVO.getBeforeValue())));
                        beanWrapper.setPropertyValue(modifiedFieldVO.getField(), afterDate);
                    } else {
                        beanWrapper.setPropertyValue(
                                modifiedFieldVO.getField(), modifiedFieldVO.getAfterValue());
                    }
                }
            }
        }
    }

    private void checkCanRollback(Oplog oplog, RollbackVO rollbackVO) {
        boolean ignoreYm = rollbackVO.getIgnoreYm();
        String routerId = oplog.getRouterId();
        String funcId = oplog.getFuncId();
        OplogRouter oplogRouter = getRouter(routerId);
        OplogFunction oplogFunction = getFunction(funcId);
        // 如果路由和功能都配置了参数，优先使用功能配置的参数，功能配置为空则使用路由的参数
        if (oplogRouter != null && !BoolEnum.TRUE.getType().equals(oplogRouter.getDel())) {
            if (oplogFunction != null) {
                if (StringUtils.isNotBlank(oplogFunction.getAuditFlag())) {
                    oplogRouter.setAuditFlag(oplogFunction.getAuditFlag());
                }
                if (StringUtils.isNotBlank(oplogFunction.getOperating())) {
                    oplogRouter.setOperating(oplogFunction.getOperating());
                }
                if (StringUtils.isNotBlank(oplogFunction.getLogFlag())) {
                    oplogRouter.setLogFlag(oplogFunction.getLogFlag());
                }
                if (StringUtils.isNotBlank(oplogFunction.getRollbackFlag())) {
                    oplogRouter.setRollbackFlag(oplogFunction.getRollbackFlag());
                }
                if (StringUtils.isNotBlank(oplogFunction.getSpanRollbackFlag())) {
                    oplogRouter.setSpanRollbackFlag(oplogFunction.getSpanRollbackFlag());
                }
            }
            if (StringUtils.isBlank(oplogRouter.getRollbackFlag())) {
                throw new AppException("该页面功能未配置是否允许回退，默认不允许回退");
            }
            if (BoolEnum.FALSE.getType().equals(oplogRouter.getRollbackFlag())) {
                throw new AppException("该页面功能配置不允许回退");
            }
            if (BoolEnum.TRUE.getType().equals(oplogRouter.getSpanRollbackFlag())) {
                ignoreYm = true;
            }
            if (!ignoreYm || !OperatingEnum.no.getType().equals(oplogRouter.getOperating())) {
                if (StringUtils.isBlank(oplogRouter.getOperating())) {
                    // 无操作期控制，不忽略业务的情况按跨月不能回退处理
                    int opYm = oplog.getDateYm();
                    int dateym =
                            Integer.parseInt(
                                    DatePattern.PURE_DATE_FORMAT
                                            .format(new Date())
                                            .substring(0, 6));
                    // 业务期 目前没有日历，直接用系统时间
                    if (BoolEnum.FALSE.getType().equals(oplogRouter.getSpanRollbackFlag())) {
                        if (dateym > opYm) {
                            throw new AppException("该业务不允许跨业务期回退");
                        }
                    }
                } else {
                    OperationPeriodVO operationPeriodVO =
                            operationPeriodIntegration.getCurrentByOperating(
                                    oplogRouter.getOperating());
                    if (operationPeriodVO.getPeriodSameId() - oplog.getPeriodSameId() != 0) {
                        throw new AppException("该业务不允许跨业务期回退");
                    }
                }
            }
        }
        if (!rollbackVO.getCheckAfterOpLog()
                && !AuTypeEnum.AUDIT.getType().equals(oplog.getAuType())) {
            String ignoreRbOp = "";
            if (oplogRouter != null && StringUtils.isBlank(oplogRouter.getIgnoreRbOp())) {
                ignoreRbOp = oplogRouter.getIgnoreRbOp();
            }
            if (oplogFunction != null && StringUtils.isBlank(oplogFunction.getIgnoreRbOp())) {
                ignoreRbOp = oplogFunction.getIgnoreRbOp();
            }
            if (StringUtils.isNotBlank(ignoreRbOp)) {
                List<String> opList =
                        Arrays.stream(ignoreRbOp.split(","))
                                .map(s -> s)
                                .collect(Collectors.toList());
                if (opList.contains(oplog.getOperationType())) {
                    rollbackVO.setCheckAfterOpLog(false);
                }
            }
        }
    }

    private OplogRouter getRouter(String routerId) {
        if (StringUtils.isBlank(routerId)) {
            return null;
        }
        OplogRouter oplogRouter = null;
        if (redisHelper.hHasKey(CacheConst.SYSTEM_ROUTER_PRIVILEGE_ID, routerId)) {
            RouterVO routerVO =
                    (RouterVO) redisHelper.hget(CacheConst.SYSTEM_ROUTER_PRIVILEGE_ID, routerId);
            oplogRouter = Convert.convert(OplogRouter.class, routerVO);
        } else {
            oplogRouter = oplogRouterService.getById(routerId);
        }
        return oplogRouter;
    }

    @Override
    public OplogFunction getFunction(String funcId) {
        if (StringUtils.isBlank(funcId)) {
            return null;
        }
        OplogFunction oplogFunction = null;
        if (redisHelper.hHasKey(CacheConst.SYS_FUNCTION_FUNCID, funcId)) {
            FunctionVO functionVO =
                    (FunctionVO) redisHelper.hget(CacheConst.SYS_FUNCTION_FUNCID, funcId);
            oplogFunction = Convert.convert(OplogFunction.class, functionVO);
        } else {
            oplogFunction = oplogFunctionService.getById(funcId);
        }
        return oplogFunction;
    }

    @Override
    @OpApi(
            funcCode = "OPLOG0006",
            title = "保存用户经办备注",
            funcType = FuncTypeEnum.edit,
            checkPrivilege = BoolEnum.FALSE,
            savelog = false)
    public String saveOrUpdateUserRemarks(OplogUserRemarksVO vo) {
        String userId = SessionUtil.getUserId();
        QueryWrapper<OplogUserRemarks> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(OplogUserRemarks::getBusNo, vo.getBusNo())
                .eq(OplogUserRemarks::getUserId, userId);
        List<OplogUserRemarks> list = oplogUserRemarksService.list(queryWrapper);
        String id = IdUtil.fastSimpleUUID();
        if (CollectionUtils.isEmpty(list)) {
            if (StringUtils.isBlank(vo.getRemarks())) {
                return null;
            }
        } else {
            id = list.get(0).getId();
        }
        OplogUserRemarks oplogUserRemarks = new OplogUserRemarks();
        oplogUserRemarks.setId(id);
        oplogUserRemarks.setBusNo(vo.getBusNo());
        oplogUserRemarks.setRemarks(vo.getRemarks());
        oplogUserRemarks.setUserId(userId);
        oplogUserRemarksService.saveOrUpdate(oplogUserRemarks);
        return id;
    }

    @Override
    @OpApi(
            funcCode = "OPLOG0007",
            title = "根据批量总日志id获取多条日志",
            funcType = FuncTypeEnum.query,
            checkPrivilege = BoolEnum.FALSE,
            savelog = false)
    public PageInfo<OplogVO> getBatchOplog(OplogDetailVO vo) {
        // 开启分页
        if (vo.getPageNum() != null && vo.getPageSize() != null) {
            PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        }
        QueryWrapper<Oplog> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(Oplog::getUnionOplogId, vo.getOplogId())
                .eq(Oplog::getRbStatus, "0")
                .eq(Oplog::getStatus, "1");
        List<Oplog> oplogVOList = oplogService.list(queryWrapper);
        List<OplogVO> list = Convert.toList(OplogVO.class, oplogVOList);
        if (CollectionUtils.isEmpty(oplogVOList)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<OplogVO> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<OplogVO> resultList = Convert.toList(OplogVO.class, pageInfo.getList());
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    private static boolean isNumeric(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        for (int i = str.length(); --i >= 0; ) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}
